#include "s3c2440.h"
#include "uart.h"
#include "mad.h"
//#include "mp31.h"
#include "sine1.h"
unsigned char end[1024*1024*8];
static char *heap_ptr;
unsigned int membyte[30];
unsigned int ptrcnt;
/*
 * This is perhaps the simplest example use of the MAD high-level API.
 * Standard input is mapped into memory via mmap(), then the high-level API
 * is invoked with three callbacks: input, output, and error. The output
 * callback converts MAD's high-resolution PCM samples to 16 bits, then
 * writes them to standard output in little-endian, stereo-interleaved
 * format.
 */

static int decode(unsigned char const *, unsigned long);

int main(int argc, char *argv[])
{
#ifdef xxx
    struct stat stat;
    void *fdm;

    if (argc != 1)
        return 1;

    if (fstat(STDIN_FILENO, &stat) == -1 ||
        stat.st_size == 0)
        return 2;

    fdm = mmap(0, stat.st_size, PROT_READ, MAP_SHARED, STDIN_FILENO, 0);
    if (fdm == MAP_FAILED)
        return 3;
#endif

    unsigned char *buffer;
    unsigned long buffersize;
    printf("libmad test begin \n");
    //comdownload();
    //printf("download mp3 ok \n");
    //buffer=(unsigned char *)(0x30900000);
    //buffer=mp31;
    buffer = sine1;
    buffersize=sizeof(sine1);
    heap_ptr = end;
    ptrcnt=0;
    // decode(fdm, stat.st_size);
    decode(buffer,buffersize);

    // if (munmap(fdm, stat.st_size) == -1)
    //   return 4;
    while (1)
    {
    }
    return 0;
}

/*
 * This is a private message structure. A generic pointer to this structure
 * is passed to each of the callback functions. Put here any data you need
 * to access from within the callbacks.
 */

struct buffer
{
    unsigned char const *start;
    unsigned long length;
};

/*
 * This is the input callback. The purpose of this callback is to (re)fill
 * the stream buffer which is to be decoded. In this example, an entire file
 * has been mapped into memory, so we just call mad_stream_buffer() with the
 * address and length of the mapping. When this callback is called a second
 * time, we are finished decoding.
 */

static
enum mad_flow input(void *data,
                    struct mad_stream *stream)
{
    struct buffer *buffer = data;
    printf("input fun\n");
    if (!buffer->length)
        return MAD_FLOW_STOP;

    mad_stream_buffer(stream, buffer->start, buffer->length);

    buffer->length = 0;

    return MAD_FLOW_CONTINUE;
}

/*
 * The following utility routine performs simple rounding, clipping, and
 * scaling of MAD's high-resolution samples down to 16 bits. It does not
 * perform any dithering or noise shaping, which would be recommended to
 * obtain any exceptional audio quality. It is therefore not recommended to
 * use this routine if high-quality output is desired.
 */

static inline
signed int scale(mad_fixed_t sample)
{
    /* round */
    sample += (1L << (MAD_F_FRACBITS - 16));

    /* clip */
    if (sample >= MAD_F_ONE)
        sample = MAD_F_ONE - 1;
    else if (sample < -MAD_F_ONE)
        sample = -MAD_F_ONE;

    /* quantize */
    return sample >> (MAD_F_FRACBITS + 1 - 16);
}

/*
 * This is the output callback function. It is called after each frame of
 * MPEG audio data has been completely decoded. The purpose of this callback
 * is to output (or play) the decoded PCM audio.
 */

static
enum mad_flow output(void *data,
                     struct mad_header const *header,
                     struct mad_pcm *pcm)
{
    unsigned int nchannels, nsamples;
    mad_fixed_t const *left_ch, *right_ch;

    /* pcm->samplerate contains the sampling frequency */

    nchannels = pcm->channels;
    nsamples  = pcm->length;
    left_ch   = pcm->samples[0];
    right_ch  = pcm->samples[1];

    while (nsamples--)
    {
        signed int sample;

        /* output sample(s) in 16-bit signed little-endian PCM */

        sample = scale(*left_ch++);
        //putchar((sample >> 0) & 0xff);
        //printf("%x\n",(sample >>0)&0xff);
        //putch((sample >> 0)& 0xff);
        //putchar((sample >> 8) & 0xff);
        //putch((sample >> 8) & 0xff);
         //printf("%d\n",(sample >>8)&0xff);
        sample&=0xffff;
        if(sample <=0x7fff)
        {
            printf("%d\n",sample&0xffff);
        }
        else
        {
            printf("-%d\n",0x10000-sample&0xffff);
        }

        if (nchannels == 2)
        {
            sample = scale(*right_ch++);
            //putchar((sample >> 0) & 0xff);
           // putch((sample >> 0)&0xff);
          //   printf("%x\n",(sample >>0)&0xff);
            //putchar((sample >> 8) & 0xff);
           // putch((sample >> 8) & 0xff);
            // printf("%d\n",(sample >>0)&0xff);
          //  printf("%d\n",sample&0xffff);
        }
    }

    return MAD_FLOW_CONTINUE;
}

/*
 * This is the error callback function. It is called whenever a decoding
 * error occurs. The error is indicated by stream->error; the list of
 * possible MAD_ERROR_* errors can be found in the mad.h (or stream.h)
 * header file.
 */

static
enum mad_flow error(void *data,
                    struct mad_stream *stream,
                    struct mad_frame *frame)
{
    struct buffer *buffer = data;

//  fprintf(stderr, "decoding error 0x%04x (%s) at byte offset %u\n",
    //  stream->error, mad_stream_errorstr(stream),
    //stream->this_frame - buffer->start);
    //printf("decoding error 0x%x %s %d\n",stream->error,mad_stream_errorstr(stream),
    //      stream->this_frame-buffer->start);
    printf("error\n");

    /* return MAD_FLOW_BREAK here to stop decoding (and propagate an error) */

    return MAD_FLOW_CONTINUE;
}

/*
 * This is the function called by main() above to perform all the decoding.
 * It instantiates a decoder object and configures it with the input,
 * output, and error callback functions above. A single call to
 * mad_decoder_run() continues until a callback function returns
 * MAD_FLOW_STOP (to stop decoding) or MAD_FLOW_BREAK (to stop decoding and
 * signal an error).
 */

static
int decode(unsigned char const *start, unsigned long length)
{
    struct buffer buffer;
    struct mad_decoder decoder;
    int result;

    /* initialize our private message structure */

    buffer.start  = start;
    buffer.length = length;

    /* configure input, output, and error functions */

    mad_decoder_init(&decoder, &buffer,
                     input, 0 /* header */, 0 /* filter */, output,
                     error, 0 /* message */);

    /* start decoding */

    result = mad_decoder_run(&decoder, MAD_DECODER_MODE_SYNC);

    /* release the decoder */
    printf("finish\n");
    mad_decoder_finish(&decoder);

    return result;
}

void *mymalloc(int nbytes)
{
    char  *base;        /*  errno should be set to  ENOMEM on error  */

    if (!heap_ptr)    /*  Initialize if first time through.  */
    {
        heap_ptr = end;
        ptrcnt = 0;
    }
    base = heap_ptr;    /*  Point to end of heap.  */
    heap_ptr += nbytes; /*  Increase heap.  */
    membyte[ptrcnt] = nbytes;
    ptrcnt++;
    return base;        /*  Return pointer to start of new heap area.  */
}

void *mycalloc(unsigned int n_items, unsigned int sizeof_item)
{
    unsigned int size;
    void *p;
    size = n_items*sizeof_item;
    p = mymalloc(size);
    if(p != 0)
    {
        mem_set0((unsigned char *)p, size);
    }
    
    return p;
}

void
mem_set0 (unsigned char * mem, unsigned int n)
{
  while (n--)
    *(mem++) = 0;
}

void myfree(void *ptr)
{
    heap_ptr-=membyte[ptrcnt-1];
    return;
}
